#pragma once
#ifndef CLASS_ANGLE_SELF 
#define CLASS_ANGLE_SELF
#include <string> 
#include <iostream>
#include <vector>
#include <algorithm>

#include "TH1.h"
#include "TSystem.h"
#include "TStyle.h"
#include "TCanvas.h"
#include "TChain.h"
#include "TClonesArray.h"
#include "TLorentzVector.h"

#include "src/Lib/MessageFormat.h"
#include "src/Class/Variable.h"

class AComb_Angle_Self{
	private:
		int _nout1, _nout2, _nleft1, _nleft2, _ncomb;
		std::string              _title;
		int _num_out1_out1  , _num_out1_out2  , _num_out1_comb , _num_out1_left1  , _num_out1_left2;
		int _num_out2_out2  , _num_out2_comb , _num_out2_left1  , _num_out2_left2;
		int _num_comb_comb;
		int _num_left1_comb, _num_left1_left1 , _num_left1_left2;
		int _num_left2_comb, _num_left2_left2;
		int _num;
	public:
		AComb_Angle_Self(){
			_title = "";
			_nout1 = 0, _nout2 = 0, _nleft1 = 0, _nleft2 = 0, _ncomb = 0;
			_num_out1_out1 = 0, _num_out1_out2 = 0, _num_out1_comb = 0, _num_out1_left1 = 0, _num_out1_left2 = 0;
			_num_out2_out2 = 0, _num_out2_comb = 0, _num_out2_left1 = 0, _num_out2_left2 = 0;
			_num_comb_comb = 0;
			_num_left1_comb= 0, _num_left1_left1= 0, _num_left1_left2= 0;
			_num_left2_comb= 0, _num_left2_left2= 0;
			_num = 0;
		}

		std::vector<double> out1_out1_angle;
		std::vector<double> out2_out2_angle;
		std::vector<double> out1_out2_angle;
		std::vector<double> out1_comb_angle;
		std::vector<double> out2_comb_angle;
		std::vector<double> comb_comb_angle;
		std::vector<double> left1_left1_angle;
		std::vector<double> left2_left2_angle;
		std::vector<double> left1_left2_angle;
		std::vector<double> left1_comb_angle;
		std::vector<double> left2_comb_angle;
		std::vector<double> out1_left1_angle;
		std::vector<double> out1_left2_angle;
		std::vector<double> out2_left1_angle;
		std::vector<double> out2_left2_angle;

		std::map<std::string, std::vector<double> > angles;

		void Set_Single_Variable(std::string name, std::vector<double> data);
		void Set_Variables();
		void Set_Title(std::string str){
			_title = str;
		};

		void Set_Single_Param(std::string name, int value);
		void Set_Param(int nout1, int nout2, int nleft1, int nleft2, int ncomb = 1);

		void Set_Angle(std::vector<TLorentzVector> &out1, std::vector<TLorentzVector> &out2, std::vector<TLorentzVector> &left1, std::vector<TLorentzVector> &left2, TLorentzVector &comb);

		void Assign_Variables(AVariable &var);

		int Num(std::string name);

		void Print(int level = 2, std::string str="");
};


class AComb_DeltaR_Self{
	private:
		int _nout1, _nout2, _nleft1, _nleft2, _ncomb;
		std::string              _title;
	public:
		std::vector<double> out1_out1_DeltaR;
		std::vector<double> out2_out2_DeltaR;
		std::vector<double> out1_out2_DeltaR;
		std::vector<double> out1_comb_DeltaR;
		std::vector<double> out2_comb_DeltaR;
		std::vector<double> comb_comb_DeltaR;
		std::vector<double> left1_left1_DeltaR;
		std::vector<double> left2_left2_DeltaR;
		std::vector<double> left1_left2_DeltaR;
		std::vector<double> left1_comb_DeltaR;
		std::vector<double> left2_comb_DeltaR;
		std::vector<double> out1_left1_DeltaR;
		std::vector<double> out1_left2_DeltaR;
		std::vector<double> out2_left1_DeltaR;
		std::vector<double> out2_left2_DeltaR;

		std::map<std::string, std::vector<double> > DeltaRs;

		void Set_Single_Variable(std::string name, std::vector<double> data);
		void Set_Variables();
		void Set_Title(std::string str){
			_title = str;
		};


		void Set_Single_Param(std::string name, int value);
		void Set_Param(int nout1, int nout2, int nleft1, int nleft2, int ncomb=1);

		void Set_DeltaR(std::vector<TLorentzVector> &out1, std::vector<TLorentzVector> &out2, std::vector<TLorentzVector> &left1, std::vector<TLorentzVector> &left2, TLorentzVector &comb);

		void Print(int level = 2, std::string str="");
};


class AComb_DeltaPhi_Self{
	private:
		int _nout1, _nout2, _nleft1, _nleft2, _ncomb;
		std::string              _title;
	public:
		std::vector<double> out1_out1_DeltaPhi;
		std::vector<double> out2_out2_DeltaPhi;
		std::vector<double> out1_out2_DeltaPhi;
		std::vector<double> out1_comb_DeltaPhi;
		std::vector<double> out2_comb_DeltaPhi;
		std::vector<double> comb_comb_DeltaPhi;
		std::vector<double> left1_left1_DeltaPhi;
		std::vector<double> left2_left2_DeltaPhi;
		std::vector<double> left1_left2_DeltaPhi;
		std::vector<double> left1_comb_DeltaPhi;
		std::vector<double> left2_comb_DeltaPhi;
		std::vector<double> out1_left1_DeltaPhi;
		std::vector<double> out1_left2_DeltaPhi;
		std::vector<double> out2_left1_DeltaPhi;
		std::vector<double> out2_left2_DeltaPhi;

		std::map<std::string, std::vector<double> > DeltaPhis;

		void Set_Single_Variable(std::string name, std::vector<double> data);
		void Set_Variables();
		void Set_Title(std::string str){
			_title = str;
		};


		void Set_Single_Param(std::string name, int value);
		void Set_Param(int nout1, int nout2, int nleft1, int nleft2, int ncomb=1);

		void Set_DeltaPhi(std::vector<TLorentzVector> &out1, std::vector<TLorentzVector> &out2, std::vector<TLorentzVector> &left1, std::vector<TLorentzVector> &left2, TLorentzVector &comb);

		void Print(int level = 2, std::string str="");
};


#endif
